/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.ui.laf;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;

import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;

import org.isqlviewer.swing.table.Sortable;

/**
 * @author Markus A. Kobold &lt;mkobold at sprintpcs dot com&gt;
 */
public class SortableHeaderRenderer extends DefaultTableCellRenderer implements TableColumnModelListener {

    private static final long serialVersionUID = 1302200480018755232L;

    public static int SORT_ICON_WIDTH = 4;

    private int sortedColumn = -1;
    private String sortedColumnName = null;
    private boolean sortAsc = false;
    private int renderColumn = -1;

    public SortableHeaderRenderer(JTable table) {

        table.getColumnModel().addColumnModelListener(this);
        setBorder(UIManager.getBorder("TableHeader.cellBorder"));
        setHorizontalTextPosition(LEFT);
        setHorizontalAlignment(CENTER);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
            int row, int column) {

        if (table != null) {
            JTableHeader header = table.getTableHeader();
            if (header != null) {
                setForeground(header.getForeground());
                setBackground(header.getBackground());
            }

            if (sortedColumnName != null && renderColumn == column) {
                String tColumn = table.getColumnName(column);
                if (tColumn != null) {
                    if (tColumn.compareTo(sortedColumnName) == 0)
                        if (sortAsc) {
                            setIcon(new BasicArrowIcon(SwingConstants.SOUTH, SORT_ICON_WIDTH));
                        } else {
                            setIcon(new BasicArrowIcon(SwingConstants.NORTH, SORT_ICON_WIDTH));
                        }
                } else {
                    setIcon(null);
                }
            } else {
                setIcon(null);
            }

            Icon ico = getIcon();
            if (ico != null) {
                setSize(getPreferredSize().width + ico.getIconWidth(), getHeight());
            } else {
                setSize(getPreferredSize());
            }
            setText((value == null) ? "" : value.toString());
        }
        return this;
    }

    /**
     * Tells listeners that the selection model of the TableColumnModel changed.
     */
    public void columnSelectionChanged(ListSelectionEvent e) {

    }

    /** Tells listeners that a column was moved due to a margin change. */
    public void columnMarginChanged(ChangeEvent e) {

    }

    /** Tells listeners that a column was repositioned. */
    public void columnMoved(TableColumnModelEvent e) {

        if (renderColumn == -1)
            return;

        int from = e.getFromIndex();
        int to = e.getToIndex();

        if (to == from) // actually hasn't finished moving...
            return;

        if (to == renderColumn) // another column is moved to this current sorted column
            renderColumn = from;
        else if (from == renderColumn)
            renderColumn = to;
    }

    /** Tells listeners that a column was removed from the model. */
    public void columnRemoved(TableColumnModelEvent e) {

    }

    /** Tells listeners that a column was added to the model. */
    public void columnAdded(TableColumnModelEvent e) {

    }

    public boolean isAscending() {

        return sortAsc;
    }

    public int getSortedColumn() {

        return sortedColumn;
    }

    public int getRenderedSortedColumn() {

        return renderColumn;
    }

    public synchronized void setSortedColumn(int column, JTable jTable, boolean asc) {

        synchronized (this) {
            if (column < 0 || !(jTable.getModel() instanceof Sortable)) {
                sortedColumn = -1;
                sortedColumnName = null;
                sortAsc = false;
                renderColumn = -1;
            } else {
                Sortable mdl = (Sortable) jTable.getModel();
                sortAsc = asc;
                renderColumn = column;
                sortedColumnName = jTable.getColumnName(column);
                sortedColumn = mdl.getIndexOfColumnName(sortedColumnName);
            }
        }

    }

    public static class BasicArrowIcon implements Icon, SwingConstants {

        private int direction = NORTH;
        private int size = 0;

        public BasicArrowIcon() {

            this(EAST);
        }

        public BasicArrowIcon(int dir) {

            this(dir, 16);
        }

        public BasicArrowIcon(int dir, int size) {

            this.size = size;
            direction = dir;
        }

        public int getIconHeight() {

            return size;
        }

        public int getIconWidth() {

            return size;
        }

        public void paintIcon(Component c, Graphics g, int x, int y) {

            Color oldColor = g.getColor();
            int mid, i, j;
            boolean isEnabled = c.isEnabled();

            j = 0;
            size = Math.max(size, 2);
            mid = size / 2;

            g.translate(x, y);
            if (isEnabled)
                g.setColor(UIManager.getColor("controlDkShadow"));
            else
                g.setColor(UIManager.getColor("controlShadow"));

            switch (direction) {
                case NORTH :
                    for (i = 0; i < size; i++) {
                        g.drawLine(mid - i, i, mid + i, i);
                    }
                    if (!isEnabled) {
                        g.setColor(UIManager.getColor("controlLtHighlight"));
                        g.drawLine(mid - i + 2, i, mid + i, i);
                    }
                    break;
                case SOUTH :
                    if (!isEnabled) {
                        g.translate(1, 1);
                        g.setColor(UIManager.getColor("controlLtHighlight"));

                        for (i = size - 1; i >= 0; i--) {
                            g.drawLine(mid - i, j, mid + i, j);
                            j++;
                        }
                        g.translate(-1, -1);
                        g.setColor(UIManager.getColor("controlShadow"));
                    }
                    j = 0;
                    for (i = size - 1; i >= 0; i--) {
                        g.drawLine(mid - i, j, mid + i, j);
                        j++;
                    }
                    break;
                case WEST :
                    for (i = 0; i < size; i++) {
                        g.drawLine(i, mid - i, i, mid + i);
                    }
                    if (!isEnabled) {
                        g.setColor(UIManager.getColor("controlLtHighlight"));
                        g.drawLine(i, mid - i + 2, i, mid + i);
                    }
                    break;
                case EAST :
                    if (!isEnabled) {
                        g.translate(1, 1);
                        g.setColor(UIManager.getColor("controlLtHighlight"));
                        for (i = size - 1; i >= 0; i--) {
                            g.drawLine(j, mid - i, j, mid + i);
                            j++;
                        }
                        g.translate(-1, -1);
                        g.setColor(UIManager.getColor("controlShadow"));
                    }
                    j = 0;
                    for (i = size - 1; i >= 0; i--) {
                        g.drawLine(j, mid - i, j, mid + i);
                        j++;
                    }
                    break;
            }
            g.translate(-x, -y);
            g.setColor(oldColor);
        }

    }
}